package edu.thu.studio.ormdesigner.editor.editpart;

import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.ChopboxAnchor;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;

import edu.thu.studio.ormdesigner.editor.figure.NodeFigure;
import edu.thu.studio.ormdesigner.editor.policy.NodeComponentEditPolicy;
import edu.thu.studio.ormdesigner.editor.policy.NodeGraphicalNodeEditPolicy;
import edu.thu.studio.ormdesigner.model.diagram.node.Node;
import edu.thu.studio.ormdesigner.util.Utils;

public abstract class NodeEditPart extends AbstractModelEditPart implements DeleteableEditPart,
    org.eclipse.gef.NodeEditPart {
    
    @Override
    public void doPropertyChange(PropertyChangeEvent event) {
        if (event.getPropertyName().equals("refreshSourceConnections")) {
            this.refreshSourceConnections();
        } else if (event.getPropertyName().equals("refreshTargetConnections")) {
            this.refreshTargetConnections();
        }
        super.doPropertyChange(event);
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    protected void createEditPolicies() {
        this.installEditPolicy(EditPolicy.COMPONENT_ROLE, new NodeComponentEditPolicy());
        this.installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new NodeGraphicalNodeEditPolicy());
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    final public void refreshVisuals() {
        this.doRefreshVisuals();
        
        Node element = (Node) this.getModel();
        IFigure figure = this.getFigure();
        
        Rectangle rectangle = this.getRectangle();
        
        GraphicalEditPart parent = (GraphicalEditPart) this.getParent();
        
        parent.setLayoutConstraint(this, figure, rectangle);
        
        this.getFigure().getUpdateManager().performValidation();
        
        element.setRectangle(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
        
    }
    
    protected Rectangle getRectangle() {
        Node element = (Node) this.getModel();
        
        Point point = new Point(element.getX(), element.getY());
        
        Dimension dimension = new Dimension(element.getWidth(), element.getHeight());
        
        return new Rectangle(point, dimension);
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    @SuppressWarnings("rawtypes")
    protected List getModelSourceConnections() {
        Node element = (Node) this.getModel();
        return element.getOutgoings();
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    @SuppressWarnings("rawtypes")
    protected List getModelTargetConnections() {
        Node element = (Node) this.getModel();
        return element.getIncomings();
    }
    
    public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connection) {
        return new ChopboxAnchor(getFigure());
    }
    
    public ConnectionAnchor getSourceConnectionAnchor(Request request) {
        return new ChopboxAnchor(getFigure());
    }
    
    public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connection) {
        return new ChopboxAnchor(getFigure());
    }
    
    public ConnectionAnchor getTargetConnectionAnchor(Request request) {
        return new ChopboxAnchor(getFigure());
    }
    
    public boolean isDeleteable() {
        return true;
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void performRequest(Request request) {
        if (request.getType().equals(RequestConstants.REQ_OPEN)) {
            try {
                performRequestOpen();
                
            } catch (Exception e) {
                Utils.showExceptionDialog(e);
            }
        }
        
        super.performRequest(request);
    }
    
    abstract protected void performRequestOpen();
    
    @Override
    @SuppressWarnings("rawtypes")
    protected List getModelChildren() {
        List<Object> modelChildren = new ArrayList<Object>();
        Node node = (Node) this.getModel();
        modelChildren.addAll(node.getColumns().getObjectList());
        return modelChildren;
    }
    
    public void doRefreshVisuals() {
        NodeFigure figure = (NodeFigure) this.getFigure();
        Node node = (Node) this.getModel();
        if (null != node.getName()) {
            figure.setName(node.getName());
        } else if (null != node.getCode()) {
            figure.setName(node.getCode());
        }
        
        for (Object child : this.getChildren()) {
            ColumnEditPart part = (ColumnEditPart) child;
            part.refreshColumns();
        }
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public IFigure getContentPane() {
        NodeFigure figure = (NodeFigure) super.getContentPane();
        return figure.getColumns();
    }
    
}
